package com.liwie.app;

//静态变量在哪里？【堆里面】
//1——方法区存在一个c语言的Class对象，因此该对象里面也拥有静态变量
//2——堆区存在一个java语言的Class对象，因此该对象里面也拥有静态变量（只不过程序员是调用的堆区中的Class对象，因此对于java程序员来说静态变量在堆里面）
//堆区和方法区都是线程共享的
//堆区的数据是可以改变的，因此着重考虑线程共享同一数据的问题
//方法区的数据是不可以改变的，因此无需考虑线程共享同一数据的问题【只读】

//一个接口里面只有唯一一个抽象方法，即可以使用朗姆达表达式
//@FunctionalInterface表达该接口可以使用朗姆达表达式，表达该接口为函数接口
//朗姆达表达式：()->{}
//朗姆达表达式是弱类型语法

//线程不安全是指多线程访问共享数据，如果涉及到修改，则会发生不安全现象
//StringBuilder是线程不安全
//StringBuffer是线程安全
//List集合中线程安全的是Vector
//Set集合中线程安全的是SynchronizedSet
//Map集合中线程安全的是Hashtable
//为什么平时使用线程不安全的而不使用线程安全的【自动上锁耗费时间】

import java.util.*;
//需要解决不安全现象【同步】【没有锁就是异步【并行】】
//加锁（悲观锁）***********************************
//synchronized (锁对象)
//代码段锁住【锁对象自定义】
//方法锁住【非静态锁对象是this，静态锁对象是堆区的Class】
//上锁【第一个线程进去时刻自动上锁】
//放锁【线程执行完毕自动放锁】
public class MyApp5 {
    public static int ticket=20;
    public Object lock = new Object();

    public static boolean t=true;
    public void ticketSell(int sleep){
        while (t){
        synchronized (lock) {
            if (ticket > 0) {
                try {
                    Thread.sleep(sleep);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + ticket);
                ticket--;
            }else {
                t=false;
            }
        }
        }
    }
    Runnable r1=()->{
        ticketSell(500);
    };
    Runnable r2=()->{
        ticketSell(500);
    };
    Runnable r3=()->{
        ticketSell(500);
    };
    Thread t1=new Thread(r1,"一号窗口");
    Thread t2=new Thread(r2,"二号窗口");
    Thread t3=new Thread(r3,"三号窗口");
    public static void main(String[] args) {
        MyApp5 myApp5 = new MyApp5();
        myApp5.t1.start();
        myApp5.t2.start();
        myApp5.t3.start();
    }
   /* //朗姆达表达式
   IA ia=(x,y)->{
        System.out.println("ia"+(x+y));
    };

    public static void main(String[] args) {
        MyApp5 myApp5 = new MyApp5();
        myApp5.r1.run();
        myApp5.ia.fun(100,200);
    }*/
}
